package engine.gui.popup;

import org.lwjgl.opengl.GL11;

import engine.gui.Component;
import engine.gui.GUIStyle;
import engine.gui.WindowManager;
import engine.gui.elements.Panel;
import engine.util.ortho.Draw2D;
import engine.util.vector.Color;

public class Popup {
	private static final int CLOSE_BUTTON_OFFSET = 0;
	
	private boolean markForRemoval;
	
	private GUIStyle ownStyle;
	private GUIStyle externalStyle;
	
	private boolean forceUseOwnStyle;
	
	private Panel panel;
	
	private int posX;
	private int posY;
	private int width;
	private int height;
	
	private boolean onDrag;
	private int[] lastDragPos;
	
	public Popup(int posX, int posY, int width, int height) {
		this.posX = posX;
		this.posY = posY;
		this.width = width;
		this.height = height;
		
		panel = new Panel(0, 0, width, height);
		panel.setSolid(false);
		
		lastDragPos = new int[2];
	}
	
	public void addComponent(Component component) {
		panel.addComponent(component);
	}
	
	public void dispose() {
		markForRemoval = true;
	}

	public void render() {
		GUIStyle style = getCurrentStyle();
		
		renderWindowDecoration(style);
		
		panel.render(posX, posY, width, height);
	}
	
	public void reset() {
		panel.reset();
	}
	
	private void renderWindowDecoration(GUIStyle style) {
		Color.bindColor4f(style.getPopupHeaderColor());
		if(style.getPopupHeaderImage() != null) {
			style.getPopupHeaderImage().draw(posX, posY, width, style.getPopupHeaderHeight());
		} else {
			Draw2D.fillRect(posX, posY, width, style.getPopupHeaderHeight());
		}
		
		Color.bindColor4f(style.getPopupBodyColor());
		if(style.getPopupBodyImage() != null) {
			style.getPopupBodyImage().draw(posX, posY + style.getPopupHeaderHeight(), width, height - style.getPopupHeaderHeight());
		} else {
			Draw2D.fillRect(posX, posY + style.getPopupHeaderHeight(), width, height - style.getPopupHeaderHeight());
		}
		
		GL11.glColor4f(1, 1, 1, 1);
		if(style.getPopupCloseButtonImage() != null) {
			style.getPopupCloseButtonImage().draw(posX + width - style.getPopupHeaderHeight() - CLOSE_BUTTON_OFFSET, posY, style.getPopupHeaderHeight(), style.getPopupHeaderHeight());
		}
	}
	
	private GUIStyle getCurrentStyle() {
		return (!isForceUseOwnStyle() && externalStyle != null) ? externalStyle : ownStyle;
	}
	
	public void setWindowManager(WindowManager windowManager) {
		panel.setWindowManager(windowManager);
		
		if(windowManager != null) {
			setPositionInsideViewport();
		}
	}
	
	public void setExternalStyle(GUIStyle externalStyle) {
		this.externalStyle = externalStyle;
		panel.setExternalStyle(externalStyle);
		
		applyPanelSize();
	}
	
	private void applyPanelSize() {
		GUIStyle style = getCurrentStyle();
		
		if(style != null) {
			panel.setPosX(style.getPopupPadding());
			panel.setPosY(style.getPopupHeaderHeight() + style.getPopupPadding());
			panel.setWidth(width - style.getPopupPadding() * 2);
			panel.setHeight(height - style.getPopupPadding() * 2);
		}
	}
	
	public void setOwnStyle(GUIStyle ownStyle) {
		this.ownStyle = ownStyle;
	}
	
	public GUIStyle getOwnStyle() {
		return ownStyle;
	}
	
	public boolean keyPressed(int key) {
		return panel.keyPressed(key);
	}
	
	public boolean keyReleased(int key) {
		return panel.keyReleased(key);
	}
	
	public boolean mousePressed(int x, int y, int button) {
		GUIStyle style = getCurrentStyle();
		
		boolean ret = false;
		
		if(x > posX && x < posX + width && y > posY && y < posY + height) {
			if(y < posY + style.getPopupHeaderHeight()) {
				onDrag = true;
				lastDragPos[0] = x;
				lastDragPos[1] = y;
			}
			
			if(style.getPopupCloseButtonImage() != null) {
				if(x > posX + width - style.getPopupHeaderHeight() - CLOSE_BUTTON_OFFSET && x < posX + width - CLOSE_BUTTON_OFFSET) {
					dispose();
				}
			}
			
			ret = true;
		}
		
		return panel.mousePressed(x - posX, y - posY, button) || ret;
	}
	
	public boolean mouseReleased(int x, int y, int button) {
		onDrag = false;
		boolean ret = false;
		
		if(x > posX && x < posX + width && y > posY && y < posY + height) {
			ret = true;
		}
		
		return panel.mouseReleased(x - posX, y - posY, button) || ret;
	}
	
	public boolean mouseMoved(int x, int y, int button) {
		boolean ret = false;
		
		if(x > posX && x < posX + width && y > posY && y < posY + height) {
			ret = true;
		}
		
		return panel.mouseMoved(x - posX, y - posY, button) || ret;
	}
	
	public boolean mouseDragged(int x, int y, int button) {
		if(onDrag) {
			posX += x - lastDragPos[0];
			posY += y - lastDragPos[1];
			lastDragPos[0] = x;
			lastDragPos[1] = y;
			
			setPositionInsideViewport();
			
			return true;
		}
		return panel.mouseDragged(x - posX, y - posY, button);
	}
	
	public boolean mouseWheelMoved(int movement) {
		return panel.mouseWheelMoved(movement);
	}
	
	public boolean isForceUseOwnStyle() {
		return forceUseOwnStyle;
	}
	
	public void setForceUseOwnStyle(boolean forceUseOwnStyle) {
		this.forceUseOwnStyle = forceUseOwnStyle;
	}
	
	public boolean isMarkForRemoval() {
		return markForRemoval;
	}
	
	private void setPositionInsideViewport() {
		posX = Math.max(0, Math.min(panel.getWindowManager().getWidth() - width, posX));
		posY = Math.max(0, Math.min(panel.getWindowManager().getHeight() - height, posY));
	}
}
